<template>
  <div class="j-super-query-box">
    <div @click="visible=true">
      <slot>
        <p-tooltip
          v-if="superQueryFlag"
          :mouse-leave-delay="0.2"
        >
          <template slot="title">
            <span>已有高级查询条件生效</span>
            <p-divider type="vertical" />
            <a @click="handleReset">清空</a>
          </template>
          <p-button type="primary">
            <p-icon
              type="appstore"
              theme="twoTone"
              :spin="true"
            />
            <span>高级查询</span>
          </p-button>
        </p-tooltip>
        <p-button
          v-else
          type="primary"
          icon="filter"
          @click="visible=true"
        >
          高级查询
        </p-button>
      </slot>
    </div>

    <p-modal
      title="高级查询构造器"
      :width="1000"
      :visible="visible"
      @cancel="handleCancel"
      :mask="false"
      class="j-super-query-modal"
      style="top:5%;max-height: 95%;"
    >
      <template slot="footer">
        <div style="float: left">
          <p-button
            :loading="loading"
            @click="handleReset"
          >
            重置
          </p-button>
          <p-button
            :loading="loading"
            @click="handleSave"
          >
            保存查询条件
          </p-button>
        </div>
        <p-button
          :loading="loading"
          @click="handleCancel"
        >
          关闭
        </p-button>
        <p-button
          :loading="loading"
          type="primary"
          @click="handleOk"
        >
          查询
        </p-button>
      </template>

      <p-spin :spinning="loading">
        <p-row>
          <p-col
            :sm="24"
            :md="24-5"
          >
            <p-empty v-if="queryParamsModel.length === 0">
              <div slot="description">
                <span>没有任何查询条件</span>
                <p-divider type="vertical" />
                <a @click="handleAdd">点击新增</a>
              </div>
            </p-empty>

            <p-form
              v-else
              layout="inline"
            >
              <p-form-item
                label="过滤条件匹配"
                style="margin-bottom: 12px;"
              >
                <p-select
                  v-model="selectValue"
                  :get-popup-container="node=>node.parentNode"
                >
                  <p-select-option value="and">
                    AND（所有条件都要求匹配）
                  </p-select-option>
                  <p-select-option value="or">
                    OR（条件中的任意一个匹配）
                  </p-select-option>
                </p-select>
              </p-form-item>

              <p-row
                type="flex"
                style="margin-bottom:10px"
                :gutter="16"
                v-for="(item, index) in queryParamsModel"
                :key="index"
              >
                <p-col :span="8">
                  <p-tree-select
                    show-search
                    v-model="item.field"
                    :tree-data="fieldTreeData"
                    :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
                    placeholder="选择查询字段"
                    allow-clear
                    tree-default-expand-all
                    :get-popup-container="node=>node.parentNode"
                    style="width: 100%"
                    @select="(val,option)=>handleSelected(option,item)"
                  />
                </p-col>

                <p-col :span="4">
                  <p-select
                    placeholder="匹配规则"
                    v-model="item.rule"
                    :get-popup-container="node=>node.parentNode"
                  >
                    <p-select-option value="eq">
                      等于
                    </p-select-option>
                    <p-select-option value="ne">
                      不等于
                    </p-select-option>
                    <p-select-option value="gt">
                      大于
                    </p-select-option>
                    <p-select-option value="ge">
                      大于等于
                    </p-select-option>
                    <p-select-option value="lt">
                      小于
                    </p-select-option>
                    <p-select-option value="le">
                      小于等于
                    </p-select-option>
                    <p-select-option value="right_like">
                      以..开始
                    </p-select-option>
                    <p-select-option value="left_like">
                      以..结尾
                    </p-select-option>
                    <p-select-option value="like">
                      包含
                    </p-select-option>
                    <p-select-option value="in">
                      在...中
                    </p-select-option>
                  </p-select>
                </p-col>

                <p-col :span="8">
                  <template v-if="item.dictCode">
                    <template v-if="item.type === 'table-dict'">
                      <f-popup
                        :contextPath="item.contextPath"
                        v-model="item.val"
                        :code="item.dictTable"
                        :field="item.dictCode"
                        :org-fields="item.dictCode"
                        :dest-fields="item.dictCode"
                      />
                    </template>
                    <j-dict-select-tag
                      v-else
                      v-model="item.val"
                      :dict-code="item.dictCode"
                      placeholder="请选择"
                    />
                  </template>
                  <j-select-multi-user
                    v-else-if="item.type === 'select-user'"
                    v-model="item.val"
                    :buttons="false"
                    :multiple="false"
                    placeholder="请选择用户"
                    :return-keys="['id', item.customReturnField || 'username']"
                  />
                  <j-select-depart
                    v-else-if="item.type === 'select-depart'"
                    v-model="item.val"
                    :multi="false"
                    placeholder="请选择部门"
                    :custom-return-field="item.customReturnField || 'id'"
                  />
                  <p-select
                    v-else-if="item.options instanceof Array"
                    v-model="item.val"
                    :options="item.options"
                    allow-clear
                    placeholder="请选择"
                  />

                  <j-date
                    v-else-if=" item.type=='date' "
                    v-model="item.val"
                    placeholder="请选择日期"
                    style="width: 100%"
                  />
                  <j-date
                    v-else-if=" item.type=='datetime' "
                    v-model="item.val"
                    placeholder="请选择时间"
                    :show-time="true"
                    date-format="YYYY-MM-DD HH:mm:ss"
                    style="width: 100%"
                  />
                  <p-input-number
                    v-else-if=" item.type=='int'||item.type=='number' "
                    style="width: 100%"
                    placeholder="请输入数值"
                    v-model="item.val"
                  />
                  <p-input
                    v-else
                    v-model="item.val"
                    placeholder="请输入值"
                  />
                </p-col>

                <p-col :span="4">
                  <p-button
                    @click="handleAdd"
                    icon="plus"
                  />&nbsp;
                  <p-button
                    @click="handleDel( index )"
                    icon="minus"
                  />
                </p-col>
              </p-row>
            </p-form>
          </p-col>
          <p-col
            :sm="24"
            :md="5"
          >
            <!-- 查询记录 -->

            <p-card
              class="j-super-query-history-card"
              :bordered="true"
            >
              <div slot="title">
                保存的查询
              </div>

              <p-empty
                v-if="treeData.length === 0"
                class="j-super-query-history-empty"
                description="没有保存任何查询"
              />
              <p-tree
                v-else
                class="j-super-query-history-tree"
                show-icon
                :tree-data="treeData"
                @select="handleTreeSelect"
                @rightClick="handleTreeRightClick"
              />
            </p-card>
          </p-col>
        </p-row>
      </p-spin>

      <p-modal
        title="请输入保存的名称"
        :visible="prompt.visible"
        @cancel="prompt.visible=false"
        @ok="handlePromptOk"
      >
        <p-input v-model="prompt.value" />
      </p-modal>
    </p-modal>
  </div>
</template>

<script>
import * as utils from '@/utils/util'
import JDate from '@/components/jeecg/JDate.vue'
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'

export default {
  name: 'JSuperQuery',
  components: {
    JDictSelectTag,
    JDate
  },
  props: {
    /*
       fieldList: [{
          value:'',
          text:'',
          type:'',
          dictCode:'' // 只要 dictCode 有值，无论 type 是什么，都显示为字典下拉框
       }]
       type:date datetime int number string
      * */
    fieldList: {
      type: Array,
      required: true
    },
    /*
      * 这个回调函数接收一个数组参数 即查询条件
      * */
    callback: {
      type: String,
      required: false,
      default: 'handleSuperQuery'
    },

    // 当前是否在加载中
    loading: {
      type: Boolean,
      default: false
    },

    // 保存查询条件的唯一 code，通过该 code 区分
    saveCode: {
      type: String,
      default: 'testSaveCode'
    }

  },
  data () {
    return {
      fieldTreeData: [],

      prompt: {
        visible: false,
        value: ''
      },

      visible: false,
      queryParamsModel: [{}],
      treeIcon: <p-icon type="file-text"/>,
      treeData: [],
      // 保存查询条件的前缀名
      saveCodeBefore: 'JSuperQuerySaved_',
      selectValue: 'and',
      superQueryFlag: false
    }
  },
  watch: {
    // 当 saveCode 变化时，重新查询已保存的条件
    saveCode: {
      immediate: true,
      handler (val) {
        const list = this.$ls.get(this.saveCodeBefore + val)
        if (list instanceof Array) {
          this.treeData = list.map(item => {
            item.icon = this.treeIcon
            return item
          })
        }
      }
    },
    fieldList: {
      deep: true,
      immediate: true,
      handler (val) {
        const mainData = []; 
        const subData = [];
        val = val || [];
        val.forEach(item => {
          const data = { ...item }
          data.label = data.label || data.text
          const hasChildren = (data.children instanceof Array)
          data.disabled = hasChildren
          data.selectable = !hasChildren
          if (hasChildren) {
            data.children = data.children.map(item2 => {
              const child = { ...item2 }
              child.label = child.label || child.text
              child.label = data.label + '-' + child.label
              child.value = data.value + ',' + child.value
              child.val = ''
              return child
            })
            data.val = ''
            subData.push(data)
          } else {
            mainData.push(data)
          }
        })
        this.fieldTreeData = mainData.concat(subData)
      }
    }
  },

  methods: {
    show () {
      if (!this.queryParamsModel || this.queryParamsModel.length == 0) {
        this.queryParamsModel = [{}]
      }
      this.visible = true
    },
    handleOk () {
      if (!this.isNullArray(this.queryParamsModel)) {
        const event = {
          matchType: this.selectValue,
          params: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
        }
        console.log('---高级查询参数--->', event)
        this.emitCallback(event.params, event.matchType)
      } else {
        this.emitCallback()
      }
    },
    emitCallback (params, matchType) {
      this.superQueryFlag = !!params
      this.$emit(this.callback, params, matchType)
    },
    handleCancel () {
      this.close()
    },
    close () {
      this.$emit('close')
      this.visible = false
    },
    handleAdd () {
      this.queryParamsModel.push({})
    },
    handleDel (index) {
      this.queryParamsModel.splice(index, 1)
    },
    handleSelected (node, item) {
      const { type, options, dictCode, dictTable, customReturnField } = node.dataRef
      item['type'] = type
      item['options'] = options
      item['dictCode'] = dictCode
      item['dictTable'] = dictTable
      item['customReturnField'] = customReturnField
      this.$set(item, 'val', undefined)
    },
    handleReset () {
      this.superQueryFlag = false
      this.queryParamsModel = [{}]
      this.emitCallback()
    },
    handleSave () {
      const queryParams = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
      if (this.isNullArray(queryParams)) {
        this.$message.warning('空条件不能保存')
      } else {
        this.prompt.value = ''
        this.prompt.visible = true
      }
    },
    handlePromptOk () {
      const { value } = this.prompt
      // 判断有没有重名

      const filterList = this.treeData.filter(i => i.title === value)
      if (filterList.length > 0) {
        this.$confirm({
          content: `${value} 已存在，是否覆盖？`,
          onOk: () => {
            this.prompt.visible = false
            filterList[0].records = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
            this.saveToLocalStore()
            this.$message.success('保存成功')
          }
        })
      } else {
        this.prompt.visible = false
        this.treeData.push({
          title: value,
          icon: this.treeIcon,
          records: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
        })
        this.saveToLocalStore()
        this.$message.success('保存成功')
      }
    },
    handleTreeSelect (idx, event) {
      if (event.selectedNodes[0]) {
        this.queryParamsModel = utils.cloneObject(event.selectedNodes[0].data.props.records)
      }
    },
    handleTreeRightClick (args) {
      this.$confirm({
        content: '是否删除当前查询？',
        onOk: () => {
          const { node: { eventKey } } = args
          this.treeData.splice(Number.parseInt(eventKey.substring(2)), 1)
          this.saveToLocalStore()
          this.$message.success('删除成功')
        }
      })
    },

    // 将查询保存到 LocalStore 里
    saveToLocalStore () {
      this.$ls.set(this.saveCodeBefore + this.saveCode, this.treeData.map(item => {
        return { title: item.title, records: item.records }
      }))
    },

    isNullArray (array) {
      // 判断是不是空数组对象
      if (!array || array.length === 0) {
        return true
      }
      if (array.length === 1) {
        const obj = array[0]
        if (!obj.field || (obj.val == null || obj.val === '') || !obj.rule) {
          return true
        }
      }
      return false
    },
    // 去掉数组中的空对象
    removeEmptyObject (array) {
      for (let i = 0; i < array.length; i++) {
        const item = array[i]
        if (item == null || Object.keys(item).length <= 0) {
          array.splice(i--, 1)
        } else {
          // 去掉特殊属性
          delete item.options
        }
      }
      return array
    }
  }
}
</script>

<style lang="less" scoped>

  .j-super-query-box {
    display: inline-block;
  }

  .j-super-query-modal {

    .j-super-query-history-card /deep/ {
      .poros-card-body,
      .poros-card-head-title {
        padding: 0;
      }

      .poros-card-head {
        padding: 4px 8px;
        min-height: initial;
      }
    }

    .j-super-query-history-empty /deep/ {
      .poros-empty-image {
        height: 80px;
        line-height: 80px;
        margin-bottom: 0;
      }

      img {
        width: 80px;
        height: 65px;
      }

      .poros-empty-description {
        color: #afafaf;
        margin: 8px 0;
      }
    }

    .j-super-query-history-tree /deep/ {
      .poros-tree-switcher {
        display: none;
      }

      .poros-tree-node-content-wrapper {
        width: 100%;
      }
    }

  }

</style>
